home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume13 / vn.jan.88 / part03 < prev    next >
Encoding:
Internet Message Format  |  1988-01-30  |  41.6 KB

  1. Subject:  v13i021:  VN newsreader, 1/88 version, Part03/05
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Bob Mcqueer <amdahl!rtech!rtech!bobm@UUNET.UU.NET>
  7. Posting-number: Volume 13, Issue 21
  8. Archive-name: vn.jan.88/part03
  9.  
  10. #! /bin/sh
  11. # This is a shell archive, meaning:
  12. # 1. Remove everything above the #! /bin/sh line.
  13. # 2. Save the resulting text in a file.
  14. # 3. Execute the file with /bin/sh (not csh) to create the files:
  15. #    envir_set.c
  16. #    getch.c
  17. #    hash.c
  18. #    newdisp.c
  19. #    printex.c
  20. #    reg.c
  21. #    sig_set.c
  22. #    stat.c
  23. #    storage.c
  24. #    strings.c
  25. #    strtok.c
  26. #    svart.c
  27. #    term_set.c
  28. #    tmpnam.c
  29. #    tty_set.c
  30. #    userlist.c
  31. #    vnglob.c
  32. # This archive created: Sat Jan  9 12:40:08 1988
  33. export PATH; PATH=/bin:$PATH
  34. echo shar: extracting "'envir_set.c'" '(2837 characters)'
  35. if test -f 'envir_set.c'
  36. then
  37.     echo shar: will not over-write existing file "'envir_set.c'"
  38. else
  39. cat << \SHAR_EOF > 'envir_set.c'
  40. /*
  41. ** vn news reader.
  42. **
  43. ** envir_set.c - routine to obtain pertinent environment variable settings
  44. **        and set up file / directory names
  45. **
  46. ** see copyright disclaimer / history in vn.c source file
  47. */
  48.  
  49. #include <stdio.h>
  50. #include <pwd.h>
  51. #include <sys/param.h>
  52. #include "tune.h"
  53. #include "config.h"
  54. #include "vn.h"
  55.  
  56. extern char *Editor, *Ps1, *Printer;
  57. extern char *Orgdir, *Savedir, *Ccfile;    /* path names */
  58. extern char Cxitop[], Cxitor[], Cxrtoi[], Cxptoi[];
  59. extern char *Home;
  60. extern int More;
  61.  
  62. #ifdef SYSV
  63. extern char *getcwd();
  64. #define getwd(a) getcwd(a,sizeof(a))
  65. #define    MAXPATHLEN 240
  66. #else
  67. extern char *getwd();
  68. #endif
  69.  
  70. /*
  71.     environment variable, original directory string setup.
  72. */
  73.  
  74. envir_set ()
  75. {
  76.     char dbuf [MAXPATHLEN], *ccname, *keyxln;
  77.     char *vn_env(), *getcwd(), *str_store();
  78.     struct passwd *ptr, *getpwuid();
  79.  
  80.     vns_envir();
  81.     More = 0;
  82.  
  83.     Ps1 = vn_env("PS1",DEF_PS1);
  84.     Editor = vn_env("EDITOR",DEF_ED);
  85.     Printer = vn_env("PRINTER",DEF_PRINT);
  86.     ccname = vn_env("CCFILE",DEF_CCFILE);
  87.     keyxln = vn_env("VNKEY",DEF_KEYXLN);
  88.     Savedir = vn_env("VNSAVE",NULL);
  89.     More = (strcmp(vn_env("MORE",""), "-c") == 0 ? TRUE : FALSE);
  90.  
  91.     /*
  92.         set original directory strings.
  93.     */
  94.  
  95.     if ((ptr = getpwuid(getuid())) == NULL)
  96.         printex("Cannot obtain /etc/passwd entry");
  97.     Home = str_store(ptr->pw_dir);
  98.     if ((Orgdir = getwd(dbuf)) == NULL)
  99.         printex ("cannot stat pwd");
  100.     Orgdir = str_store (Orgdir);
  101.     if (Savedir == NULL)
  102.         Savedir = Orgdir;
  103.     if (*ccname != '/')
  104.     {
  105.         sprintf (dbuf, "%s/%s",Home,ccname);
  106.         Ccfile = str_store (dbuf);
  107.     }
  108.     else
  109.         Ccfile = str_store (ccname);
  110.     sprintf (dbuf, "%s/%s%s",Home,".vn","XXXXXX");
  111.  
  112.     if (*keyxln != '/')
  113.     {
  114.         sprintf(dbuf, "%s/%s",Home,keyxln);
  115.         set_kxln(dbuf);
  116.     }
  117.     else
  118.         set_kxln(keyxln);
  119. }
  120.  
  121. char *
  122. vn_env(var,def)
  123. char *var;
  124. char *def;
  125. {
  126.     char pfx[RECLEN];
  127.     char *res;
  128.     char *getenv();
  129.  
  130.     if (var[0] != 'V' || var[1] != 'N')
  131.     {
  132.         sprintf(pfx,"VN%s",var);
  133.         if ((res = getenv(pfx)) != NULL)
  134.             return(res);
  135.     }
  136.  
  137.     if ((res = getenv(var)) != NULL)
  138.         return(res);
  139.  
  140.     return(def);
  141. }
  142.  
  143. static
  144. set_kxln(fname)
  145. char *fname;
  146. {
  147.     FILE *fp;
  148.     int i;
  149.     char bufr[80];
  150.     char in,out,*ptr;
  151.     char *index(), xln_str();
  152.  
  153.     for (i=0; i < 128; ++i)
  154.         Cxitop[i] = Cxitor[i] = Cxptoi[i] = Cxrtoi[i] = i;
  155.  
  156.     if ((fp = fopen(fname,"r")) != NULL)
  157.     {
  158.         while(fgets(bufr,79,fp) != NULL)
  159.         {
  160.             if (strncmp(bufr+1,"==",2) == 0)
  161.                 ptr = bufr+2;
  162.             else
  163.                 ptr = index(bufr+1,'=');
  164.             if (ptr == NULL)
  165.                 continue;
  166.             *ptr = '\0';
  167.             ++ptr;
  168.             in = xln_str(bufr+1);
  169.             out = xln_str(ptr);
  170.             switch(bufr[0])
  171.             {
  172.             case 'r':
  173.             case 'R':
  174.                 Cxrtoi[out] = in;
  175.                 Cxitor[in] = out;
  176.                 break;
  177.             case 'p':
  178.             case 'P':
  179.                 Cxptoi[out] = in;
  180.                 Cxitop[in] = out;
  181.             default:
  182.                 break;
  183.             }
  184.         }
  185.         fclose(fp);
  186.     }
  187. }
  188.  
  189. static char
  190. xln_str(s)
  191. char *s;
  192. {
  193.     if (*s < '0' || *s > '9')
  194.         return(*s & 0x7f);
  195.     return((char)(atoi(s) & 0x7f));
  196. }
  197. SHAR_EOF
  198. fi # end of overwriting check
  199. echo shar: extracting "'getch.c'" '(1924 characters)'
  200. if test -f 'getch.c'
  201. then
  202.     echo shar: will not over-write existing file "'getch.c'"
  203. else
  204. cat << \SHAR_EOF > 'getch.c'
  205. /*
  206. ** vn news reader.
  207. **
  208. ** getch.c - character i/o routines
  209. **
  210. ** see copyright disclaimer / history in vn.c source file
  211. */
  212. #include <stdio.h>
  213. #include <setjmp.h>
  214. #include "config.h"
  215. #include "vn.h"
  216.  
  217. extern char Cxitop[];
  218. extern char *Ku, *Kd, *Kr, *Kl;
  219.  
  220. /*
  221.     getkey obtains user keystroke with count from leading
  222.     numerics, if any.  Picks up arrow key sequences and maps
  223.     them to other keys.  Also translates character through
  224.     Cxitop array since this routine is only used in session
  225.     loop.  Saves untranslating arrow keys.
  226. */
  227. getkey (c)
  228. char *c;
  229. {
  230.     int i, j;
  231.     static char    ckseq[32];
  232.  
  233.     /* Check for leading count */
  234.     for (i = 0; (*c = getchar() & 0x7f) >= '0' && *c <= '9'; i = i * 10 + *c - '0')
  235.         ;
  236.  
  237.     /* @#$!!! flakey front ends that won't map newlines in raw mode */
  238.     if (*c == '\012' || *c == '\015')
  239.         *c = '\n';
  240.  
  241.     /* @#$!!! flakey terminals which send control sequences for cursors! */
  242.     if( *c == '\033' )
  243.     {
  244.         /*
  245.         ** Check if part of cursor key input sequence
  246.         ** (pitch unknown escape sequences)
  247.         */
  248.         j = 0;
  249.         ckseq[j] = *c; ckseq[j+1] = '\0';
  250.         while(*c == Ku[j] || *c == Kd[j] || *c == Kl[j] || *c == Kr[j])
  251.         {
  252.             if( strcmp(ckseq, Ku) == 0 ) { *c = UP; break; }
  253.             if( strcmp(ckseq, Kd) == 0 ) { *c = DOWN; break; }
  254. #ifdef PAGEARROW
  255.             if( strcmp(ckseq, Kl) == 0 ) { *c = BACK; break; }
  256.             if( strcmp(ckseq, Kr) == 0 ) { *c = FORWARD; break; }
  257. #else
  258.             if( strcmp(ckseq, Kl) == 0 ) { *c = UP; break; }
  259.             if( strcmp(ckseq, Kr) == 0 ) { *c = DOWN; break; }
  260. #endif
  261.             *c = (getchar() & 0x7f);
  262.             ckseq[++j] = *c; ckseq[j+1] = '\0';
  263.         }
  264.     }
  265.     else
  266.         *c = Cxitop[*c];
  267.  
  268.     if (i <= 0)
  269.         i = 1;
  270.     return (i);
  271. }
  272.  
  273. /*
  274.     get user key ignoring most controls.  Used from reader and other
  275.     non-screen interactions.
  276. */
  277. getnoctl ()
  278. {
  279.     char c;
  280.     while ((c = getchar() & 0x7f) < ' ' || c == '\177')
  281.     {
  282.         if (c == '\015' || c == '\012')
  283.             c = '\n';
  284.         if (c == '\n' || c == '\b' || c == '\t')
  285.             return (c);
  286.     }
  287.     return ((int) c);
  288. }
  289. SHAR_EOF
  290. fi # end of overwriting check
  291. echo shar: extracting "'hash.c'" '(1874 characters)'
  292. if test -f 'hash.c'
  293. then
  294.     echo shar: will not over-write existing file "'hash.c'"
  295. else
  296. cat << \SHAR_EOF > 'hash.c'
  297. /*
  298. ** vn news reader.
  299. **
  300. ** hash.c - hash table routines
  301. **
  302. ** see copyright disclaimer / history in vn.c source file
  303. */
  304.  
  305. #include <stdio.h>
  306. #include "config.h"
  307. #include "tune.h"
  308. #include "node.h"
  309.  
  310. /*
  311. ** hash table manipulation routines:
  312. */
  313.  
  314. extern int Ncount;
  315. extern NODE **Newsorder;
  316.  
  317. static NODE *Tab [HASHSIZE];    /* hash Table */
  318.  
  319. hashinit ()
  320. {
  321.     int i;
  322.     for (i=0; i < HASHSIZE; ++i)
  323.         Tab[i] = NULL;
  324.     Ncount = 0;
  325. }
  326.  
  327. /*
  328.     enter new node (name s, articles n, low l) in hash Table, 
  329.     initial flags = 0.  Set order to -1.
  330. */
  331. NODE *hashenter(s,n,l)
  332. char *s;
  333. int n;
  334. int l;
  335. {
  336.     char *str_store();
  337.     NODE *ptr,*node_store();
  338.     NODE *hashfind();
  339.     int i;
  340.  
  341.     if ((ptr = hashfind(s)) != NULL)
  342.     {
  343.         fgprintf ("Warning: group %s encountered twice",s);
  344.         return (ptr);
  345.     }
  346.  
  347.     i=hash(s);
  348.     ptr = node_store();
  349.     ptr->next = Tab[i];
  350.     Tab[i] = ptr;
  351.     if (l > n)
  352.         l = n;
  353.     ++Ncount;
  354.     ptr->lownum = l;
  355.     ptr->state = 0;
  356.     ptr->data = NULL;
  357.     ptr->flags = 0;
  358.     ptr->highnum = n;
  359.     ptr->nd_name = str_store(s);
  360.     ptr->pgshwn = 0;
  361.     ptr->order = -1;
  362.     return (ptr);
  363. }
  364.  
  365. NODE *hashfind(s)
  366. char *s;
  367. {
  368.     NODE *ptr;
  369.  
  370.     for (ptr = Tab[hash(s)]; ptr != NULL && strcmp(ptr->nd_name,s) != 0;
  371.                     ptr = ptr->next)
  372.             ;
  373.     return (ptr);
  374. }
  375.  
  376. make_newsorder()
  377. {
  378.     char *malloc();
  379.     int i;
  380.     NODE *ptr;
  381.  
  382.     if ((Newsorder = (NODE **) malloc(Ncount * sizeof(NODE *))) == NULL)
  383.         printex("Memory allocation failure - newsorder array");
  384.     for (i=0; i < Ncount; ++i)
  385.         Newsorder[i] = NULL;
  386.     for (i=0; i < HASHSIZE; ++i)
  387.     {
  388.         for (ptr = Tab[i]; ptr != NULL; ptr = ptr->next)
  389.         {
  390.             if (ptr->order < 0 || ptr->order >= Ncount)
  391.                 printex("News order range error");
  392.             Newsorder[ptr->order] = ptr;
  393.         }
  394.     }
  395.     for (i=0; i < Ncount; ++i)
  396.         if (Newsorder[i] == NULL)
  397.             printex("News order duplication error");
  398. }
  399.  
  400. static hash (s)
  401. char *s;
  402. {
  403.     unsigned rem;
  404.     for (rem=0; *s != '\0'; ++s)
  405.         rem = (rem*128 + (*s&0x7f)) % HASHSIZE;
  406.     return (rem);
  407. }
  408. SHAR_EOF
  409. fi # end of overwriting check
  410. echo shar: extracting "'newdisp.c'" '(920 characters)'
  411. if test -f 'newdisp.c'
  412. then
  413.     echo shar: will not over-write existing file "'newdisp.c'"
  414. else
  415. cat << \SHAR_EOF > 'newdisp.c'
  416. /*
  417. ** vn news reader.
  418. **
  419. ** newgroups.c - display list of new groups since user's last ession.
  420. **
  421. ** see copyright disclaimer / history in vn.c source file
  422. */
  423.  
  424. #include <stdio.h>
  425. #include "config.h"
  426. #include "tty.h"
  427. #include "node.h"
  428.  
  429. extern NODE **Newsorder;
  430. extern int Ncount, Lrec, C_allow;
  431.  
  432. new_groups ()
  433. {
  434.     int i,wrem,w;
  435.     int max;
  436.     char fs[24],c_end;
  437.  
  438.     max = 0;
  439.     for (i=0; i < Ncount; ++i)
  440.         if (((Newsorder[i])->flags & FLG_NEW) != 0 &&
  441.                 (w = strlen((Newsorder[i])->nd_name)) > max)
  442.             max = w;
  443.     sprintf (fs,"%%-%ds%%c",max);
  444.  
  445.     if (max <= 0)
  446.         return (0);
  447.  
  448.     term_set (ERASE);
  449.     printf ("New newsgroups:\n");
  450.  
  451.     wrem = C_allow;
  452.     for (i=0; i < Ncount; ++i)
  453.     {
  454.         if (((Newsorder[i])->flags & FLG_NEW) == 0)
  455.             continue;
  456.         if ((wrem -= max) < max)
  457.         {
  458.             wrem = C_allow;
  459.             c_end = '\n';
  460.         }
  461.         else
  462.             c_end = ' ';
  463.         printf (fs,(Newsorder[i])->nd_name,c_end);
  464.     }
  465.     if (c_end != '\n')
  466.         putchar ('\n');
  467.  
  468.     return (1);
  469. }
  470. SHAR_EOF
  471. fi # end of overwriting check
  472. echo shar: extracting "'printex.c'" '(678 characters)'
  473. if test -f 'printex.c'
  474. then
  475.     echo shar: will not over-write existing file "'printex.c'"
  476. else
  477. cat << \SHAR_EOF > 'printex.c'
  478. /*
  479. ** vn news reader.
  480. **
  481. ** printex.c - print fatal error message and exit.
  482. **
  483. ** see copyright disclaimer / history in vn.c source file
  484. */
  485. #include <stdio.h>
  486. #include <setjmp.h>
  487. #include "config.h"
  488. #include "tty.h"
  489.  
  490. extern int errno;    /* unix error number */
  491.  
  492. /*
  493.     error/abnormal condition cleanup and abort routine
  494.     pass stack to printf
  495. */
  496. printex (s,a,b,c,d,e,f)
  497. char *s;
  498. long a,b,c,d,e,f;
  499. {
  500.     static int topflag=0;
  501.     if (topflag == 0)
  502.     {
  503.         ++topflag;
  504.         term_set (STOP);
  505.         tty_set (COOKED);
  506.         fflush (stdout);
  507.         fprintf (stderr,s,a,b,c,d,e,f);
  508.         fprintf (stderr," (error code %d)\n",errno);
  509.         vns_exit(1);
  510.         stat_end(-1);
  511.         exit (1);
  512.     }
  513.     else
  514.         fprintf (stderr,s,a,b,c,d,e,f);
  515. }
  516. SHAR_EOF
  517. fi # end of overwriting check
  518. echo shar: extracting "'reg.c'" '(1656 characters)'
  519. if test -f 'reg.c'
  520. then
  521.     echo shar: will not over-write existing file "'reg.c'"
  522. else
  523. cat << \SHAR_EOF > 'reg.c'
  524. /*
  525. ** vn news reader.
  526. **
  527. ** reg.c - implementation of regex / regcmp on top of UCB library
  528. **
  529. ** see copyright disclaimer / history in vn.c source file
  530. */
  531.  
  532. #include <stdio.h>
  533.  
  534. #define RGBLKSIZE 20
  535.  
  536. struct _regtab
  537. {
  538.     struct _regtab *link;
  539.     char *regstr;
  540. };
  541.  
  542. typedef struct _regtab REGTAB;
  543.  
  544. static REGTAB *Chain = NULL;
  545. static REGTAB *Free = NULL;
  546. static REGTAB *Compiled = NULL;
  547.  
  548. regfree(s)
  549. char *s;
  550. {
  551.     REGTAB *ptr,*cmp,*old;
  552.  
  553.     cmp = (REGTAB *) s;
  554.     old = NULL;
  555.  
  556.     for (ptr = Chain; ptr != NULL; ptr = (old = ptr)->link)
  557.     {
  558.         if (ptr == cmp)
  559.         {
  560.             if (old == NULL)
  561.                 Chain = Chain->link;
  562.             else
  563.                 old->link = ptr->link;
  564.             ptr->link = Free;
  565.             Free = ptr;
  566.             break;
  567.         }
  568.     }
  569. }
  570.  
  571. char *regcmp(str)
  572. char *str;
  573. {
  574.     int i;
  575.     char *str_store();
  576.     char *re_comp();
  577.  
  578.     if (re_comp(str) != NULL)
  579.     {
  580.         Compiled = NULL;    /* make sure we're OK */
  581.         return(NULL);
  582.     }
  583.  
  584.     if (Free == NULL)
  585.     {
  586.         Free = (REGTAB *) malloc(RGBLKSIZE * sizeof(REGTAB));
  587.         if (Free == NULL)
  588.             printex ("regcmp: memory allocation failure");
  589.         for (i = 0; i < RGBLKSIZE - 1; ++i)
  590.             Free[i].link = Free + i + 1;
  591.         Free[i].link = NULL;
  592.     }
  593.  
  594.     Compiled = Free;
  595.     Free = Free->link;
  596.  
  597.     Compiled->link = Chain;
  598.     Chain = Compiled;
  599.     Compiled->regstr = str_store(str);
  600.  
  601.     return ((char *) Compiled);
  602. }
  603.  
  604. char *regex(reg,str)
  605. char *reg,*str;
  606. {
  607.     REGTAB *cmp;
  608.  
  609.     cmp = (REGTAB *) reg;
  610.  
  611.     if (cmp == Compiled)
  612.     {
  613.         if (re_exec(str))
  614.             return(str);
  615.         return (NULL);
  616.     }
  617.  
  618.     for (Compiled = Chain; Compiled != NULL; Compiled = Compiled->link)
  619.     {
  620.         if (Compiled == cmp)
  621.             break;
  622.     }
  623.  
  624.     if (Compiled == NULL)
  625.         printex ("regex: bad pointer");
  626.  
  627.     re_comp(Compiled->regstr);
  628.  
  629.     if (re_exec(str))
  630.         return(str);
  631.  
  632.     return(NULL);
  633. }
  634. SHAR_EOF
  635. fi # end of overwriting check
  636. echo shar: extracting "'sig_set.c'" '(4477 characters)'
  637. if test -f 'sig_set.c'
  638. then
  639.     echo shar: will not over-write existing file "'sig_set.c'"
  640. else
  641. cat << \SHAR_EOF > 'sig_set.c'
  642. /*
  643. ** vn news reader.
  644. **
  645. ** sig_set.c - signal handler
  646. **
  647. ** see copyright disclaimer / history in vn.c source file
  648. */
  649.  
  650. #include <stdio.h>
  651. #include <sys/signal.h>
  652. #include <sgtty.h>
  653. #include <setjmp.h>
  654. #include "tty.h"
  655. #include "config.h"
  656. #include "brk.h"
  657. #include "tune.h"
  658. #include "node.h"
  659. #include "page.h"
  660.  
  661. extern int L_allow;
  662. extern char *Version;
  663. extern char *Brk_fmt;
  664. extern char *Vns_version;
  665.  
  666. static int Sigflag=BRK_INIT;    /* phase of interaction */
  667. static FILE **Fpseek;        /* article reading file pointer pointer */
  668. static int Foreground;
  669. static jmp_buf Jumploc;        /* for BRK_SESS phase */
  670. static int Need_restart = 0;
  671.  
  672. /*
  673.     interrupt handler - unusual termination (longjmp and printex aborts)
  674.     if not abort, remember to reset signal trap
  675.     CAUTION - the passing of a jump buffer is a little dicey - assumes
  676.     type jump_buf is an array.
  677.  
  678.     sigcatch and sig_set control a lot of i/o on stderr also, since
  679.     it is so intimately related to signal interaction.  Note that the
  680.     SIGTSTP action causes a "stopped on tty output" if raw terminal
  681.     mode is restored by tty_set(RESTORE).  We don't get it if we were
  682.     already cooked since tty_set avoids calling ioctl if it doesn't
  683.     have to.
  684. */
  685. static sigcatch (sig)
  686. int sig;
  687. {
  688.     char buf [MAX_C+1];
  689.     int pgrp;
  690.  
  691.     /* disable signal while processing it */
  692.     signal (sig,SIG_IGN);
  693.  
  694.     switch (sig)
  695.     {
  696.     case SIGINT:
  697.     case SIGQUIT:
  698.         break;
  699.  
  700. #ifdef JOBCONTROL
  701.     case SIGTSTP:
  702.         /* ignore SIGTTOU so we don't get stopped if [kc]sh grabs the tty */
  703.         signal(SIGTTOU, SIG_IGN);
  704.         tty_set (SAVEMODE);
  705.         term_set (MOVE,0,L_allow+RECBIAS-1);
  706.         printf ("\n");
  707.         Foreground = 0;
  708.         fflush (stdout);
  709.         fflush (stderr);
  710.         signal(SIGTTOU, SIG_DFL);
  711.  
  712.         /* Send the TSTP signal to suspend our process group */
  713.         signal(SIGTSTP, SIG_DFL);
  714.         sigsetmask(0);
  715.         kill (0, SIGTSTP);
  716.  
  717.         /* WE ARE NOW STOPPED */
  718.  
  719.         /*
  720.                 WELCOME BACK!
  721.                 if terminals process group is ours, we are foregrounded again
  722.                 and can turn newsgroup name printing back on
  723.             */
  724.         tty_set (RESTORE);
  725.  
  726.         /*
  727.         ** Note concerning RESTART.  If in state BRK_IN, we simply
  728.         ** set a flag to do it upon switch to state BRK_SESS - we
  729.         ** don't want to send i/o to the terminal when we
  730.         ** background during BRK_IN phase ("stopped on tty output")
  731.         */
  732.         switch (Sigflag)
  733.         {
  734.         case BRK_SESS:
  735.             signal (SIGTSTP,sigcatch);
  736.             term_set (RESTART);
  737.             longjmp (Jumploc,1);
  738.         case BRK_IN:
  739.             Need_restart = 1;
  740.             ioctl (1,TIOCGPGRP,&pgrp);
  741.             if (pgrp == getpgrp(0))
  742.                 Foreground = 1;
  743.             break;
  744.         default:
  745.             term_set (RESTART);
  746.             break;
  747.         }
  748.         signal (SIGTSTP,sigcatch);
  749.         return;
  750. #endif
  751.     default:
  752.         printex (Brk_fmt,sig);
  753.     }
  754.  
  755.     /* QUIT and INTERRUPT signals */
  756.     switch (Sigflag)
  757.     {
  758.     case BRK_SESS:
  759.         /* if in session, ask if really a quit, do longjump if not */
  760.         term_set (ERASE);
  761.         tty_set (RAWMODE);
  762.         user_str (buf, BRK_PR, 1, "");
  763.         if (buf[0] == 'y')
  764.             printex (Brk_fmt,sig);
  765.         signal (sig,sigcatch);
  766.         longjmp (Jumploc,1);
  767.     case BRK_READ:
  768.         /* if reading seek file to end to abort page printing */
  769.         printf ("\n");
  770.         if (*Fpseek == NULL || fseek(*Fpseek,0L,2) < 0)
  771.             putchar ('\07');
  772.         break;
  773.     default:
  774.         printex (Brk_fmt,sig);
  775.     }
  776.     signal (sig,sigcatch);
  777. }
  778.  
  779. /*
  780.     sig_set controls what will be done with a signal when picked up by
  781.     sigcatch.  fgprintf is included here to keep knowledge
  782.     of TSTP state localized.
  783. */
  784. /* VARARGS */
  785. sig_set (flag,dat)
  786. int flag, *dat;
  787. {
  788.     int i, *xfer, pgrp;
  789.     if (Sigflag == BRK_INIT)
  790.     {
  791.         signal (SIGINT,sigcatch);
  792.         signal (SIGQUIT,sigcatch);
  793.         signal (SIGTERM,sigcatch);
  794. #ifdef JOBCONTROL
  795.         signal (SIGTSTP,sigcatch);
  796.         ioctl (1,TIOCGPGRP,&pgrp);
  797.         if (pgrp == getpgrp(0))
  798.         {
  799.             Foreground = 1;
  800.             fgprintf ("Visual News, %s(%s), reading:\n",
  801.                     Version, Vns_version);
  802.         }
  803.         else
  804.             Foreground = 0;
  805. #else
  806.         Foreground = NOJOB_FG;
  807. #endif
  808.     }
  809.     switch (flag)
  810.     {
  811.     case BRK_IN:
  812.     case BRK_OUT:
  813.         Sigflag = flag;
  814.         break;
  815.     case BRK_READ:
  816.         if (Sigflag != BRK_SESS)
  817.             printex ("unexpected read state, sig_set\n");
  818.         Fpseek = (FILE **) dat;
  819.         Sigflag = BRK_READ;
  820.         break;
  821.     case BRK_SESS:
  822.         if (Need_restart)
  823.             term_set(RESTART);
  824.         xfer = (int *) Jumploc;
  825.         for (i=0; i < sizeof(Jumploc) / sizeof(int); ++i)
  826.             xfer[i] = dat[i];
  827.         Sigflag = BRK_SESS;
  828.         break;
  829.     case BRK_RFIN:
  830.         if (Sigflag != BRK_READ)
  831.             printex ("unexpected finish state, sig_set\n");
  832.         Sigflag = BRK_SESS;
  833.         break;
  834.     default:
  835.         printex ("bad state %d, sig_set\n",flag);
  836.     }
  837. }
  838.  
  839. fgprintf (fs,a,b,c,d,e)
  840. char *fs;
  841. int a,b,c,d,e;
  842. {
  843.     if (Foreground)
  844.         fprintf (stderr,fs,a,b,c,d,e);
  845.     fflush (stderr);
  846. }
  847. SHAR_EOF
  848. fi # end of overwriting check
  849. echo shar: extracting "'stat.c'" '(4226 characters)'
  850. if test -f 'stat.c'
  851. then
  852.     echo shar: will not over-write existing file "'stat.c'"
  853. else
  854. cat << \SHAR_EOF > 'stat.c'
  855. /*
  856. ** vn news reader.
  857. **
  858. ** stat.c - stat and log file collection
  859. **
  860. ** see copyright disclaimer / history in vn.c source file
  861. */
  862. #include <stdio.h>
  863. #include <sys/types.h>
  864. #ifdef SYSV
  865. #include <fcntl.h>
  866. #endif
  867. #include <sys/file.h>
  868. #include <sys/stat.h>
  869. #include <pwd.h>
  870. #include "config.h"
  871. #include "node.h"
  872.  
  873. extern NODE *hashfind();
  874. extern char *strtok();
  875. extern int Ncount;
  876. extern NODE **Newsorder;
  877.  
  878. #ifdef VNLOGFILE
  879. static char Start[80];
  880. #endif
  881.  
  882. stat_start()
  883. {
  884. #ifdef VNLOGFILE
  885.     char *ctime();
  886.     long now;
  887.  
  888.     time(&now);
  889.     strcpy(Start,ctime(&now));
  890. #endif
  891. }
  892.  
  893. /*
  894. ** flag = 0, "NO NEWS" type session.
  895. **      = 1, regular session.
  896. **    = -1, aborted session
  897. **
  898. ** CAUTION: routine CALLED from within printex() - do NOT
  899. ** call printex().  Simply do message to stderr on fail.
  900. */
  901. stat_end(flag)
  902. int flag;
  903. {
  904.     NODE *nd;
  905.     char *nl,*index();
  906.     char *how;
  907.     struct passwd *ptr, *getpwuid();
  908.     struct stat buf;
  909.     long now;
  910.     char bufr[80];
  911.     char name[60];
  912.     FILE *fp;
  913.     int fd;
  914.     long chk, rd, pg;
  915.     int i;
  916.  
  917. #ifdef VNLOGFILE
  918.     if (stat(VNLOGFILE,&buf) == 0 && (fp = fopen(VNLOGFILE,"a")) != NULL)
  919.     {
  920.         time(&now);
  921.         strcpy(bufr,ctime(&now));
  922.         if ((nl = index(bufr,'\n')) != NULL)
  923.             *nl = '\0';
  924.         if ((nl = index(Start,'\n')) != NULL)
  925.             *nl = '\0';
  926.         if (flag == 0)
  927.             how = "NO NEWS";
  928.         else
  929.         {
  930.             if (flag > 0)
  931.                 how = "OK";
  932.             else
  933.                 how = "ABORTED";
  934.         }
  935.         ptr = getpwuid (getuid());
  936.         fprintf(fp, "%s\t%s - %s %s\n", ptr->pw_name, Start, bufr, how);
  937.         fclose (fp);
  938.     }
  939. #endif
  940.  
  941. #ifdef VNSTATFILE
  942.     /*
  943.     ** Stat file is done with a fixed record size, and maintaining the
  944.     ** existing record order exactly so that concurrent users will do
  945.     ** the least damage.  If two users actually read & update a single
  946.     ** record simultaneously, we should just lose one user's counts.
  947.     ** Short of implementing a locking scheme, we probably won't do
  948.     ** much better.  Disadvantages are that deleted newsgroups never
  949.     ** get cleaned out, order is set by the first user whose
  950.     ** statistics are collected, it will break if anyone modifies it,
  951.     ** and the file is a bit larger than it needs to be.
  952.     **
  953.     ** record format:
  954.     **
  955.     ** CCCCCC PPPPPP RRRRRR newsgroup name ....  \n
  956.     ** ^      ^      ^      ^                    ^
  957.     ** 0      7      14     21              char 79
  958.     **
  959.     ** CCCCCC - count of sessions searching group
  960.     ** PPPPPP - count of sessions actually finding pages for group
  961.     ** RRRRRR - count of sessions actually accessing articles in group
  962.     */
  963.     if ((fd = open(VNSTATFILE,O_RDWR)) > 0)
  964.     {
  965.         bufr[80] = '\0';
  966.  
  967.         /*
  968.         ** read a record, find the newsgroup, update counts.
  969.         ** If changed, seek back & overwrite.  By using fixed
  970.         ** length records, we should only lose something on
  971.         ** concurrent writes of the same record, and by writing
  972.         ** the ENTIRE record, we keep it consistent
  973.         */
  974.         while ((i = read(fd,bufr,80)) == 80 && bufr[79] == '\n')
  975.         {
  976.             chk = atoi(bufr);
  977.             pg = atoi(bufr+7);
  978.             rd = atoi(bufr+14);
  979.             strcpy(name,bufr+21);
  980.             nl = strtok(name," \n");
  981.             if (nl == NULL || (nd = hashfind(nl)) == NULL)
  982.                 continue;
  983.             nd->flags |= FLG_STAT;
  984.             if ((nd->flags & (FLG_SEARCH|FLG_ACC|FLG_PAGE)) == 0)
  985.                 continue;
  986.             if ((nd->flags & FLG_SEARCH) != 0)
  987.                 ++chk;
  988.             if ((nd->flags & FLG_PAGE) != 0)
  989.                 ++pg;
  990.             if ((nd->flags & FLG_ACC) != 0)
  991.                 ++rd;
  992.             if (chk > 999999L)
  993.                 chk = 999999L;
  994.             if (pg > 999999L)
  995.                 pg = 999999L;
  996.             if (rd > 999999L)
  997.                 rd = 999999L;
  998.             sprintf(bufr,"%6ld",chk);
  999.             bufr[6] = ' ';
  1000.             sprintf(bufr+7,"%6ld",pg);
  1001.             bufr[13] = ' ';
  1002.             sprintf(bufr+14,"%6ld",rd);
  1003.             bufr[20] = ' ';
  1004.             lseek(fd,-80L,1);
  1005.             write(fd,bufr,80);
  1006.         }
  1007.  
  1008.         /* format screwed up ? */
  1009.         if (i != 0)
  1010.         {
  1011.             lseek(fd,(long) -i,1);
  1012.             fprintf(stderr,"bad data in %s\n",VNSTATFILE);
  1013.         }
  1014.  
  1015.         /* may have aborted during vns_news() */
  1016.         if (Newsorder == NULL)
  1017.             Ncount = 0;
  1018.  
  1019.         /* now append any groups not in file yet */
  1020.         for (i = 0; i < Ncount; ++i)
  1021.         {
  1022.             nd = Newsorder[i];
  1023.             if ((nd->flags & FLG_STAT) != 0)
  1024.                 continue;
  1025.             chk = rd = pg = 0;
  1026.             if ((nd->flags & FLG_SEARCH) != 0)
  1027.                 chk = 1;
  1028.             if ((nd->flags & FLG_PAGE) != 0)
  1029.                 pg = 1;
  1030.             if ((nd->flags & FLG_ACC) != 0)
  1031.                 rd = 1;
  1032.             sprintf(bufr,"%6ld %6ld %6ld %-58s\n",
  1033.                     chk, pg, rd, nd->nd_name);
  1034.             write(fd,bufr,80);
  1035.         }
  1036.         close(fd);
  1037.     }
  1038. #endif
  1039. }
  1040. SHAR_EOF
  1041. fi # end of overwriting check
  1042. echo shar: extracting "'storage.c'" '(2261 characters)'
  1043. if test -f 'storage.c'
  1044. then
  1045.     echo shar: will not over-write existing file "'storage.c'"
  1046. else
  1047. cat << \SHAR_EOF > 'storage.c'
  1048. /*
  1049. ** vn news reader.
  1050. **
  1051. ** storage.c - storage allocation routines
  1052. **
  1053. ** see copyright disclaimer / history in vn.c source file
  1054. */
  1055.  
  1056. #include <stdio.h>
  1057. #include "tune.h"
  1058. #include "node.h"
  1059. #include "page.h"
  1060.  
  1061. extern char *malloc();
  1062.  
  1063. extern int L_allow;
  1064.  
  1065. extern PAGE Page;
  1066. /*
  1067.     Storage allocaters.
  1068. */
  1069.  
  1070. char *str_store (s)
  1071. char *s;
  1072. {
  1073.     static unsigned av_len = 0;    /* current storage available */
  1074.     static char *avail;
  1075.     int len;
  1076.  
  1077.     if (s == NULL)
  1078.         s = "";
  1079.  
  1080.     if ((len = strlen(s)+1) > av_len)
  1081.     {
  1082.         if (len > STRBLKSIZE)
  1083.             av_len = len;
  1084.         else
  1085.             av_len = STRBLKSIZE;
  1086.         if ((avail = malloc(av_len)) == NULL)
  1087.             printex ("can't allocate memory for string storage");
  1088.     }
  1089.     strcpy (avail,s);
  1090.     s = avail;
  1091.     avail += len;
  1092.     av_len -= len;
  1093.     return (s);
  1094. }
  1095.  
  1096. /*
  1097. ** called after number of terminal lines (L_allow) is known, to set
  1098. ** up storage for Page.
  1099. */
  1100. page_alloc ()
  1101. {
  1102.     char *body;
  1103.  
  1104.     if ((body = malloc(L_allow*sizeof(BODY))) == NULL)
  1105.         printex ("can't allocate memory for display storage");
  1106.  
  1107.     Page.b = (BODY *) body;
  1108. }
  1109.  
  1110. NODE
  1111. *node_store()
  1112. {
  1113.     static int nd_avail = 0;
  1114.     static NODE *nd;
  1115.     NODE *ret;
  1116.  
  1117.     if (nd_avail <= 0)
  1118.     {
  1119.         if ((nd = (NODE *) malloc(sizeof(NODE)*NDBLKSIZE)) == NULL)
  1120.             printex ("can't allocate memory for newsgroup table");
  1121.         nd_avail = NDBLKSIZE;
  1122.     }
  1123.     --nd_avail;
  1124.     ret = nd;
  1125.     ++nd;
  1126.     return(ret);
  1127. }
  1128.  
  1129. /*
  1130. ** temp string storage
  1131. */
  1132.  
  1133. typedef struct
  1134. {
  1135.     int len;
  1136.     int idx;
  1137.     char **ptr;
  1138. } STRINGPOOL;
  1139.  
  1140. char *
  1141. str_tpool(n)
  1142. int n;
  1143. {
  1144.     int size;
  1145.     STRINGPOOL *p;
  1146.  
  1147.     size = sizeof(STRINGPOOL) + n * sizeof(char **);
  1148.  
  1149.     if ((p = (STRINGPOOL *) malloc(size)) == NULL)
  1150.         printex("Cannot allocate temporary string storage");
  1151.  
  1152.     p->ptr = (char **)(p+1);
  1153.     p->len = n;
  1154.     p->idx = 0;
  1155.  
  1156.     return((char *) p);
  1157. }
  1158.  
  1159. char *
  1160. str_tstore(cp,s)
  1161. char *cp;
  1162. char *s;
  1163. {
  1164.     STRINGPOOL *p;
  1165.     int len;
  1166.  
  1167.     p = (STRINGPOOL *) cp;
  1168.     if (p->idx >= p->len)
  1169.         printex("Temporary string storage overflow");
  1170.     len = strlen(s)+1;
  1171.     if ((cp = malloc(len)) == NULL)
  1172.         printex("Cannot allocate copy of string");
  1173.     strcpy(cp,s);
  1174.     (p->ptr)[p->idx] = cp;
  1175.     ++(p->idx);
  1176.  
  1177.     return(cp);
  1178. }
  1179.  
  1180. char **
  1181. str_taptr(cp)
  1182. char *cp;
  1183. {
  1184.     STRINGPOOL *p;
  1185.  
  1186.     p = (STRINGPOOL *) cp;
  1187.  
  1188.     return (p->ptr + p->idx);
  1189. }
  1190.  
  1191. str_tfree(cp)
  1192. char *cp;
  1193. {
  1194.     STRINGPOOL *p;
  1195.     int i;
  1196.  
  1197.     p = (STRINGPOOL *) cp;
  1198.     for (i=0; i < p->idx; ++i)
  1199.         free((p->ptr)[i]);
  1200.     free (cp);
  1201. }
  1202. SHAR_EOF
  1203. fi # end of overwriting check
  1204. echo shar: extracting "'strings.c'" '(537 characters)'
  1205. if test -f 'strings.c'
  1206. then
  1207.     echo shar: will not over-write existing file "'strings.c'"
  1208. else
  1209. cat << \SHAR_EOF > 'strings.c'
  1210. /*
  1211. ** vn news reader.
  1212. **
  1213. ** strings.c - read only character strings
  1214. **
  1215. ** see copyright disclaimer / history in vn.c source file
  1216. */
  1217.  
  1218. #include "tune.h"
  1219. #include "node.h"
  1220. #include "page.h"
  1221.  
  1222. char *Version = "1/88";
  1223.  
  1224. char *No_msg = "No articles";
  1225. char *Hdon_msg = "Headers being printed";
  1226. char *Hdoff_msg = "Headers being suppressed";
  1227. char *Roton_msg = "ROT 13";
  1228. char *Rotoff_msg = "NO ROT";
  1229.  
  1230. char *Aformat = AFORMAT;
  1231.  
  1232. char *Contstr = "  ******** any key to continue ********";
  1233.  
  1234. char *Brk_fmt = "QUIT (signal %d)";
  1235.  
  1236. char *List_sep = " \t,";
  1237. SHAR_EOF
  1238. fi # end of overwriting check
  1239. echo shar: extracting "'strtok.c'" '(1082 characters)'
  1240. if test -f 'strtok.c'
  1241. then
  1242.     echo shar: will not over-write existing file "'strtok.c'"
  1243. else
  1244. cat << \SHAR_EOF > 'strtok.c'
  1245. /*
  1246. ** vn news reader.
  1247. **
  1248. ** strtok.c - strtok() and strpbrk() string routines using UCB index().
  1249. **
  1250. ** see copyright disclaimer / history in vn.c source file
  1251. */
  1252.  
  1253. #include <stdio.h>
  1254.  
  1255. char *strpbrk (s,del)
  1256. char *s, *del;
  1257. {
  1258.     char *ptr,*index();
  1259.     if (s == NULL)
  1260.         return (NULL);
  1261.     for (; *del != '\0'; ++del)
  1262.         if ((ptr = index(s,*del)) != NULL)
  1263.             return (ptr);
  1264.     return (NULL);
  1265. }
  1266.  
  1267. char *strtok(str,delim)
  1268. char *str, *delim;
  1269. {
  1270.     char *tokstart, *tokend, *first_ch (), *last_ch();
  1271.     static char *save=NULL;
  1272.  
  1273.     if (str != NULL)
  1274.         save = str;
  1275.  
  1276.     if (save == NULL)
  1277.         return (NULL);
  1278.  
  1279.     tokstart = first_ch (save, delim);
  1280.     tokend = last_ch (tokstart, delim);
  1281.     save = first_ch (tokend, delim);
  1282.     *tokend = '\0';
  1283.  
  1284.     if (*tokstart == '\0')
  1285.         return (NULL);
  1286.  
  1287.     return (tokstart);
  1288. }
  1289.  
  1290. static char *first_ch (str,delim)
  1291. char *str,*delim;
  1292. {
  1293.     char *index ();
  1294.     char *f;
  1295.  
  1296.     for (f = str; *f != '\0' && index(delim,*f) != NULL; ++f)
  1297.         ;
  1298.  
  1299.     return (f);
  1300. }
  1301.  
  1302. static char *last_ch (str,delim)
  1303. char *str,*delim;
  1304. {
  1305.     char *index ();
  1306.     char *f;
  1307.  
  1308.     for (f = str; *f != '\0' && index(delim,*f) == NULL; ++f)
  1309.         ;
  1310.  
  1311.     return (f);
  1312. }
  1313. SHAR_EOF
  1314. fi # end of overwriting check
  1315. echo shar: extracting "'svart.c'" '(4156 characters)'
  1316. if test -f 'svart.c'
  1317. then
  1318.     echo shar: will not over-write existing file "'svart.c'"
  1319. else
  1320. cat << \SHAR_EOF > 'svart.c'
  1321. /*
  1322. ** vn news reader.
  1323. **
  1324. ** svart.c - article save routine
  1325. **
  1326. ** see copyright disclaimer / history in vn.c source file
  1327. */
  1328. #include <stdio.h>
  1329. #include <pwd.h>
  1330. #include <sys/types.h>
  1331. #include <sys/stat.h>
  1332. #include "config.h"
  1333. #include "tty.h"
  1334. #include "tune.h"
  1335. #include "node.h"
  1336. #include "page.h"
  1337.  
  1338. extern PAGE Page;
  1339. extern int Digest;
  1340. extern char *List_sep;
  1341. extern char *Home;
  1342. extern char *Savedir;
  1343.  
  1344. /*
  1345. ** save article in file.  Called from reader and session both.
  1346. ** handles "|" pipe convention.  Caller passes in return message buffer.
  1347. */
  1348. save_art(art,idest,msg)
  1349. char *art;
  1350. char *idest;
  1351. char *msg;
  1352. {
  1353.     char fn[L_tmpnam+1];
  1354.     char cmd[RECLEN];
  1355.     char *mode;
  1356.     char *dest, dstore[RECLEN];
  1357.     struct stat sbuf;
  1358.     int rstat;
  1359.     char *colon;
  1360.     char *pcnt;
  1361.     char *index();
  1362.  
  1363.     /* temporary copy so we don't overwrite saved string */
  1364.     strcpy((dest = dstore),idest);
  1365.  
  1366.     if (*dest == '|')
  1367.     {
  1368.         tmpnam(fn);
  1369.         if (art_xfer(fn,art,"w") != 0)
  1370.         {
  1371.             strcpy(msg,"Can't open temporary file");
  1372.             return (-1);
  1373.         }
  1374.         sprintf(cmd,"cat %s %s",fn,dest);
  1375.         tty_set (SAVEMODE);
  1376.         rstat = system (cmd);
  1377.         tty_set (RESTORE);
  1378.         sprintf(msg,"Command returns %d",rstat);
  1379.         return (rstat);
  1380.     }
  1381.  
  1382.     if ((colon = index(dest,':')) != NULL)
  1383.     {
  1384.         mode = dest;
  1385.         *colon = '\0';
  1386.         dest = colon+1;
  1387.     }
  1388.     else
  1389.         mode = "a";
  1390.  
  1391.     if (*dest == '~')
  1392.     {
  1393.         if (twiddle(dest,msg) < 0)
  1394.             return (-1);
  1395.     }
  1396.  
  1397.     if (*dest == '\0')
  1398.         strcpy(dest,"%d");
  1399.  
  1400.     if (*dest != '/')
  1401.     {
  1402.         if (noslash(dest,msg) < 0)
  1403.             return (-1);
  1404.     }
  1405.  
  1406.     if ((pcnt = index(dest,'%')) != NULL && pcnt[1] == 'd')
  1407.     {
  1408.         if (Digest)
  1409.             sprintf(cmd,dest,Digest);
  1410.         else
  1411.             sprintf(cmd,dest,atoi(art));
  1412.         dest = cmd;
  1413.     }
  1414.  
  1415.     rstat = stat(dest,&sbuf);
  1416.  
  1417.     if (art_xfer(dest,art,mode) != 0)
  1418.     {
  1419.         sprintf(msg,"Can't open %s with mode %s",dest,mode);
  1420.         return(-1);
  1421.     }
  1422.  
  1423.     if (rstat != 0)
  1424.     {
  1425.         sprintf(msg,"Created %s",dest);
  1426.         return(0);
  1427.     }
  1428.  
  1429.     if (strcmp(mode,"a") == 0)
  1430.     {
  1431.         sprintf(msg,"Appended %s",dest);
  1432.         return(0);
  1433.     }
  1434.  
  1435.     sprintf(msg,"Wrote (mode %s) %s",mode,dest);
  1436.     return(0);
  1437. }
  1438.  
  1439. static
  1440. noslash(dest,msg)
  1441. char *dest;
  1442. char *msg;
  1443. {
  1444.     char *pcnt;
  1445.     char buf[RECLEN];
  1446.     char dir[RECLEN];
  1447.     struct stat sbuf;
  1448.  
  1449.     strcpy(buf,Page.h.name);
  1450. #ifdef SYSV
  1451.     buf[14] = '\0';
  1452. #endif
  1453.     if ((pcnt = index(Savedir,'%')) != NULL && pcnt[1] == 's')
  1454.         sprintf(dir,Savedir,buf);
  1455.     else
  1456.         strcpy(dir,Savedir);
  1457.     if (dir[0] == '~')
  1458.     {
  1459.         if (twiddle(dir,msg) < 0)
  1460.             return (-1);
  1461.     }
  1462.     if (stat(dir,&sbuf) != 0)
  1463.     {
  1464. #ifdef SYSV
  1465.         /*
  1466.         ** late enough releases of SYSV may have a mkdir() call, but
  1467.         ** this is an obscure feature anyway.  We'll accept the fork.
  1468.         */
  1469.         sprintf(buf,"mkdir %s",dir);
  1470.         if (system(buf) != 0)
  1471. #else
  1472.         if (mkdir(dir,0755) != 0)
  1473. #endif
  1474.         {
  1475.             sprintf(msg,"Cannot make directory %s",dir);
  1476.             return (-1);
  1477.         }
  1478.     }
  1479.     sprintf(buf,"%s/%s",dir,dest);
  1480.     strcpy(dest,buf);
  1481.     return (0);
  1482. }
  1483.  
  1484. static
  1485. twiddle(dest,msg)
  1486. char *dest, *msg;
  1487. {
  1488.     char *tail;
  1489.     char *name;
  1490.     char tmp;
  1491.     char buf[RECLEN];
  1492.     struct passwd *ptr, *getpwnam();
  1493.  
  1494.     for (tail=name=dest+1; *tail != '/' && *tail != '\0'; ++tail)
  1495.         ;
  1496.  
  1497.     if (*name == '\0' || *name == '/')
  1498.         sprintf(buf,"%s%s",Home,tail);
  1499.     else
  1500.     {
  1501.         tmp = *tail;
  1502.         *tail = '\0';
  1503.         ptr = getpwnam(name);
  1504.         *tail = tmp;
  1505.         if (ptr == NULL)
  1506.         {
  1507.             sprintf(msg,"Can't interpret ~%s",name);
  1508.             return(-1);
  1509.         }
  1510.         sprintf(buf,"%s%s",ptr->pw_dir,tail);
  1511.     }
  1512.  
  1513.     strcpy(dest,buf);
  1514.     return (0);
  1515. }
  1516.  
  1517. /*
  1518. ** transfer contents of a list of articles to a file.  If Digest, this
  1519. ** is simply a list of files.  If not, it is a list of articles to be
  1520. ** saved with vns_asave.  Parses list destructively with
  1521. ** strtok().  Return 0 for success, -1 for failure to open file.
  1522. **
  1523. ** Called directly to copy a list of articles to a temp. file to
  1524. ** direct to printer.
  1525. */
  1526. art_xfer(fn,list,mode)
  1527. char *fn, *list, *mode;
  1528. {
  1529.     char *p;
  1530.     FILE *fout, *fin;
  1531.     int count;
  1532.     char buf[RECLEN];
  1533.     char *strtok();
  1534.  
  1535.     if ((fout = fopen(fn,mode)) == NULL)
  1536.         return (-1);
  1537.  
  1538.     count = 0;
  1539.     for (p = strtok(list,List_sep); p != NULL; p = strtok(NULL,List_sep))
  1540.     {
  1541.         if (Digest)
  1542.         {
  1543.             fin = fopen(p,"r");
  1544.             if (fin == NULL)
  1545.                 continue;
  1546.             while (fgets(buf,RECLEN-1,fin) != NULL)
  1547.                 fputs(buf,fout);
  1548.             fclose(fin);
  1549.             continue;
  1550.         }
  1551.         vns_asave(atoi(p),fout,count,fn,mode);
  1552.         ++count;
  1553.     }
  1554.     fclose(fout);
  1555.     return(0);
  1556. }
  1557. SHAR_EOF
  1558. fi # end of overwriting check
  1559. echo shar: extracting "'term_set.c'" '(4953 characters)'
  1560. if test -f 'term_set.c'
  1561. then
  1562.     echo shar: will not over-write existing file "'term_set.c'"
  1563. else
  1564. cat << \SHAR_EOF > 'term_set.c'
  1565. /*
  1566. ** vn news reader.
  1567. **
  1568. ** term_set.c - terminal control, hides termcap interface
  1569. **
  1570. ** see copyright disclaimer / history in vn.c source file
  1571. */
  1572.  
  1573. #include <stdio.h>
  1574. #include "tty.h"
  1575. #include "config.h"
  1576. #include "tune.h"
  1577. #include "node.h"
  1578. #include "page.h"
  1579.  
  1580. extern int L_allow, C_allow;
  1581. extern char *Ku, *Kd, *Kl, *Kr;    
  1582.  
  1583. static outc (c)
  1584. char c;
  1585. {
  1586.     putchar (c);
  1587. }
  1588.  
  1589. /*
  1590.     term_set controls terminal through termcap
  1591.     START sets global parameters related to terminal also,
  1592.     as well as allocating display buffer which depends on
  1593.     terminal lines, and allocating escape strings.  RESTART
  1594.     simply re-issues the initialization - used following system
  1595.     calls that could have goofed up the terminal state.
  1596. */
  1597.  
  1598. /*
  1599. ** Escape strings.
  1600. */
  1601.  
  1602. static char *Cm,*Cl,*So,*Se,*Te,*Bc,*Ce,*Ti,*Ks,*Ke;
  1603. #ifdef USEVS
  1604. static char *Vs,*Ve;
  1605. #endif
  1606.  
  1607. static int Backspace;        /* backspace works */
  1608. static int Overstrike;        /* terminal overstrikes */
  1609.  
  1610. static t_setup()
  1611. {
  1612.     char *tgetstr(), *vn_env(), *str_store();
  1613.     char *c, tc_buf[2048],optstr[2048];
  1614.     char *tvar;
  1615.  
  1616.     tvar = vn_env("TERM",DEF_TERM);
  1617.  
  1618.     c = optstr;
  1619.     if (tgetent(tc_buf,tvar) != 1)
  1620.         printex ("%s - unknown terminal",tvar);
  1621.  
  1622.     /* get needed capabilities */
  1623.     Cm = str_store(tgetstr("cm",&c));
  1624.     Cl = str_store(tgetstr("cl",&c));
  1625.     So = str_store(tgetstr("so",&c));
  1626.     Se = str_store(tgetstr("se",&c));
  1627.     Te = str_store(tgetstr("te",&c));
  1628.     Ti = str_store(tgetstr("ti",&c));
  1629.     Bc = str_store(tgetstr("bc",&c));
  1630.     Ce = str_store(tgetstr("ce",&c));
  1631.     Kd = str_store(tgetstr("kd",&c));
  1632.     Ke = str_store(tgetstr("ke",&c));
  1633.     Kl = str_store(tgetstr("kl",&c));
  1634.     Kr = str_store(tgetstr("kr",&c));
  1635.     Ks = str_store(tgetstr("ks",&c));
  1636.     Ku = str_store(tgetstr("ku",&c));
  1637. #ifdef USEVS
  1638.     Vs = str_store(tgetstr("vs",&c));
  1639.     Ve = str_store(tgetstr("ve",&c));
  1640. #endif
  1641.     Backspace = tgetflag("bs");
  1642.     Overstrike = tgetflag("os");
  1643.  
  1644.     if ( *Cm == '\0' || *Cl == '\0')
  1645.     {
  1646.         printex ("cursor control and erase capability needed");
  1647.     }
  1648.  
  1649.     /*
  1650.     ** Checks for arrow keys which don't issue something beginning
  1651.     ** with <ESC>.  This is more paranoid than we need to be, strictly
  1652.     ** speaking - we could get away with any string which didn't
  1653.     ** conflict with controls used for commands.  However, that would
  1654.     ** be a maintenance headache - we will simply reserve <ESC> as the
  1655.     ** only char not to be used for commands, and punt on terminals
  1656.     ** which don't send reasonable arrow keys.  It would be confusing
  1657.     ** to have keys work partially, also.  I know of no terminal with
  1658.     ** one arrow key beginning with an escape, and another beginning
  1659.     ** with something else, but let's be safe.  This also insists on
  1660.     ** definitions for all 4 arrows, which seems reasonable.
  1661.     */
  1662.  
  1663.     if ((*Ku != '\0' && *Ku != '\033') || *Kl != *Ku || *Kr != *Ku || *Kd != *Ku)
  1664.     {
  1665.         fgprintf("WARNING: arrow keys will not work for this terminal");
  1666.         Ku = Kd = Kl = Kr = Kd = Ke = "";
  1667.     }
  1668.  
  1669.     if (Overstrike)
  1670.         fgprintf ("WARNING: terminal overstrikes - can't update display without erase\n");
  1671.  
  1672.     if ((L_allow = tgetnum("li")) < REQLINES)
  1673.     {
  1674.         if (L_allow < 0)
  1675.             printex ("can't determine number of lines on terminal");
  1676.         printex ("too few lines for display - %d needed", REQLINES);
  1677.     }
  1678.  
  1679.     /*
  1680.     ** C_allow set so as to not use extreme right column.
  1681.     ** Avoids "bad wraparound" problems - we're deciding it's best
  1682.     ** to ALWAYS assume no automargin, and take care of it ourselves
  1683.     */
  1684.     if((C_allow = tgetnum("co")) > MAX_C)
  1685.         C_allow = MAX_C;
  1686.     else
  1687.         --C_allow;
  1688.     if (C_allow < MIN_C)
  1689.     {
  1690.         if (C_allow < 0)
  1691.             printex("can't determine number of columns on terminal.");
  1692.         printex ("too few columns for display - %d needed",MIN_C);
  1693.     }
  1694.  
  1695.     L_allow -= RECBIAS;
  1696.     page_alloc();
  1697.     tputs(Ti,1,outc);
  1698.     tputs(Ks,1,outc);
  1699. #ifdef USEVS
  1700.     tputs(Vs,1,outc);
  1701. #endif
  1702. }
  1703.  
  1704. /* VARARGS */
  1705. term_set(cmd,x,y)
  1706. int cmd,x,y;
  1707. {
  1708.     char *tgoto();
  1709.     int i;
  1710.     switch (cmd)
  1711.     {
  1712.     case MOVE:
  1713.         tputs (tgoto(Cm,x,y),1,outc);
  1714.         break;
  1715.     case ERASE:
  1716.         tputs(Cl,1,outc);
  1717.         break;
  1718.     case ONREVERSE:
  1719.         tputs(So,1,outc);
  1720.         break;
  1721.     case OFFREVERSE:
  1722.         tputs(Se,1,outc);
  1723.         break;
  1724.     case START:
  1725.         t_setup();
  1726.         break;
  1727.     case RESTART:
  1728.         tputs(Ti,1,outc);
  1729.         tputs(Ks,1,outc);
  1730. #ifdef USEVS
  1731.         tputs(Vs,1,outc);
  1732. #endif
  1733.         break;
  1734.     case STOP:
  1735.         term_set (MOVE,0,L_allow+RECBIAS-1);
  1736.         printf ("\n");
  1737.         tputs(Ke,1,outc);
  1738.         tputs(Te,1,outc);
  1739. #ifdef USEVS
  1740.         tputs(Ve,1,outc);
  1741. #endif
  1742.         break;
  1743.     case RUBSEQ:
  1744.         if (Overstrike)
  1745.         {
  1746.             /* space overprint is futile */
  1747.             if (Backspace)
  1748.                 putchar('\010');
  1749.             else
  1750.                 tputs(Bc,1,outc);
  1751.             break;
  1752.         }
  1753.         if (Backspace)
  1754.             printf("%c %c",'\010','\010');
  1755.         else
  1756.         {
  1757.             tputs(Bc,1,outc);  
  1758.             putchar(' ');  
  1759.             tputs(Bc,1,outc);
  1760.         }
  1761.         break;
  1762.     case ZAP:
  1763.         if (Ce != NULL && *Ce != '\0')
  1764.             tputs(Ce,1,outc);
  1765.         else
  1766.         {
  1767.             if (Overstrike)
  1768.                 break;        /* punt */
  1769.             for (i=x; i < y; ++i)
  1770.                 putchar(' ');
  1771.             if (Backspace)
  1772.             {
  1773.                 for (i=x; i < y; ++i)
  1774.                     putchar('\010');
  1775.             }
  1776.             else
  1777.             {
  1778.                 for (i=x; i < y; ++i)
  1779.                     tputs(Bc,1,outc);
  1780.             }
  1781.         }
  1782.         break;
  1783.     default:
  1784.         printex ("term_set unknown code (%d)",cmd);
  1785.         break;
  1786.     }
  1787.     return (0);
  1788. }
  1789. SHAR_EOF
  1790. fi # end of overwriting check
  1791. echo shar: extracting "'tmpnam.c'" '(420 characters)'
  1792. if test -f 'tmpnam.c'
  1793. then
  1794.     echo shar: will not over-write existing file "'tmpnam.c'"
  1795. else
  1796. cat << \SHAR_EOF > 'tmpnam.c'
  1797. /*
  1798. ** vn news reader.
  1799. **
  1800. ** tmpnam.c - tmpnam() replacement for UCB, also uses non-generic name.
  1801. **
  1802. ** see copyright disclaimer / history in vn.c source file
  1803. */
  1804.  
  1805. #include <stdio.h>
  1806. #include "config.h"
  1807.  
  1808. char *tmpnam (buf)
  1809. char *buf;
  1810. {
  1811.     static char *ptr = VNTEMPNAME;
  1812.  
  1813.     /* depends on string initialized above */
  1814.     sprintf (ptr+TMP_XOFFSET,"XXXXXX");
  1815.  
  1816.     mktemp (ptr);
  1817.  
  1818.     if (buf != NULL)
  1819.         strcpy (buf,ptr);
  1820.  
  1821.     return (ptr);
  1822. }
  1823. SHAR_EOF
  1824. fi # end of overwriting check
  1825. echo shar: extracting "'tty_set.c'" '(2552 characters)'
  1826. if test -f 'tty_set.c'
  1827. then
  1828.     echo shar: will not over-write existing file "'tty_set.c'"
  1829. else
  1830. cat << \SHAR_EOF > 'tty_set.c'
  1831. /*
  1832. ** vn news reader.
  1833. **
  1834. ** tty_set.c - interface to ioctl (system tty interface)
  1835. **
  1836. ** see copyright disclaimer / history in vn.c source file
  1837. */
  1838.  
  1839. #ifdef SYSV
  1840. #include <termio.h>
  1841. #else
  1842. #include <sgtty.h>
  1843. #endif
  1844.  
  1845. #include "tty.h"
  1846.  
  1847. extern char Erasekey,Killkey;
  1848.  
  1849. #ifdef SYSV
  1850. static struct termio C_tp, O_tp;
  1851. #else
  1852. static struct sgttyb C_tp;
  1853. static unsigned short O_lflag;
  1854. #endif
  1855.  
  1856. static unsigned S_flag=0;
  1857. static int R_ignore=0;        /* up/down counter of reset calls to ignore */
  1858.  
  1859. #define IO_GOT 1    /* have polled for original terminal mode */
  1860. #define IO_RAW 2    /* in RAW (CBREAK actually) mode */
  1861.  
  1862. /*
  1863.     tty_set handles ioctl calls.  SAVEMODE, RESTORE are used around
  1864.     system calls and interrupts to assure cooked mode, and restore
  1865.     raw if raw on SAVEMODE.  The pair results in no calls to ioctl
  1866.     if we are cooked already when SAVEMODE is called, and may be nested,
  1867.     provided we desire no "restore" of cooked mode after restoring raw.
  1868.  
  1869.     When we get the original terminal mode, we also save erase and kill.
  1870.  
  1871.     sig_set makes an ioctl call to get process group leader.  Otherwise
  1872.     ioctl calls should come through here.
  1873. */
  1874. tty_set(cmd)
  1875. int cmd;
  1876. {
  1877.     int rc;
  1878.     unsigned mask;
  1879.  
  1880.     switch (cmd)
  1881.     {
  1882.     case BACKSTOP:
  1883. #ifdef JOBCONTROL
  1884.         if ((rc = ioctl(1,TIOCLGET,&mask)) != 0)
  1885.             break;
  1886.         mask |= LTOSTOP;
  1887.         rc = ioctl(1,TIOCLSET,&mask);
  1888. #else
  1889.         rc = 0;
  1890. #endif
  1891.         break;
  1892.     case RAWMODE:
  1893.         if ((S_flag & IO_RAW) != 0)
  1894.         {
  1895.             rc = 0;
  1896.             break;
  1897.         }
  1898.         if ((S_flag & IO_GOT) == 0)
  1899.         {
  1900.             /* Save original modes, get erase / kill */
  1901. #ifdef SYSV
  1902.             rc = ioctl(0,TCGETA,&C_tp);
  1903.             O_tp = C_tp;
  1904.             Erasekey = C_tp.c_cc[VERASE];
  1905.             Killkey = C_tp.c_cc[VKILL];
  1906. #else
  1907.             rc = ioctl(0,TIOCGETP,&C_tp);
  1908.             O_lflag = C_tp.sg_flags;
  1909.             Erasekey = C_tp.sg_erase;
  1910.             Killkey = C_tp.sg_kill;
  1911. #endif
  1912.         }
  1913. #ifdef SYSV
  1914.         C_tp.c_lflag &= ~(ECHO | ICANON);
  1915.         C_tp.c_cc[VMIN] = 1;
  1916.         rc = ioctl(0,TCSETAW,&C_tp);
  1917. #else
  1918.         C_tp.sg_flags |= CBREAK;
  1919.         C_tp.sg_flags &= ~ECHO;
  1920.         rc = ioctl(0,TIOCSETP,&C_tp);
  1921. #endif
  1922.         S_flag = IO_GOT|IO_RAW;
  1923.         break;
  1924.     case COOKED:
  1925.         if ((S_flag & IO_RAW) != 0)
  1926.         {
  1927. #ifdef SYSV
  1928.             C_tp = O_tp;
  1929.             rc = ioctl(0,TCSETAW,&C_tp);
  1930. #else
  1931.             C_tp.sg_flags = O_lflag;
  1932.             rc = ioctl(0,TIOCSETP,&C_tp);
  1933. #endif
  1934.             S_flag &= ~IO_RAW;
  1935.         }
  1936.         else
  1937.             rc = 0;
  1938.         break;
  1939.     case SAVEMODE:
  1940.         if ((S_flag & IO_RAW) != 0)
  1941.         {
  1942.             tty_set(COOKED);
  1943.             R_ignore = 0;
  1944.         }
  1945.         else
  1946.             ++R_ignore;
  1947.         rc = 0;
  1948.         break;
  1949.     case RESTORE:
  1950.         if (R_ignore <= 0)
  1951.         {
  1952.             tty_set(RAWMODE);
  1953.         }
  1954.         else
  1955.             --R_ignore;
  1956.         rc = 0;
  1957.         break;
  1958.     default:
  1959.         rc = -1;
  1960.     }
  1961.     if (rc < 0)
  1962.         printex ("ioctl failure, tty_set: %d",cmd);
  1963. }
  1964. SHAR_EOF
  1965. fi # end of overwriting check
  1966. echo shar: extracting "'userlist.c'" '(2130 characters)'
  1967. if test -f 'userlist.c'
  1968. then
  1969.     echo shar: will not over-write existing file "'userlist.c'"
  1970. else
  1971. cat << \SHAR_EOF > 'userlist.c'
  1972. /*
  1973. ** vn news reader.
  1974. **
  1975. ** userlist.c - generate user's list of articles
  1976. **
  1977. ** see copyright disclaimer / history in vn.c source file
  1978. */
  1979.  
  1980. #include <stdio.h>
  1981. #include "tune.h"
  1982. #include "node.h"
  1983. #include "page.h"
  1984. #include "vn.h"
  1985.  
  1986. extern PAGE Page;
  1987. extern char *List_sep;
  1988.  
  1989. static char Pattern[MAX_C] = "";
  1990.  
  1991. /*
  1992.     generate user list of articles - either article numbers
  1993.     are input directly (numeric list), or input is a search
  1994.     string - invoke regular expression library and examine titles
  1995.     search string "*" reserved for marked articles.  Strings may
  1996.     be prefixed with '!' for negation.
  1997. */
  1998. userlist (list)
  1999. char *list;
  2000. {
  2001.     int i,j,anum[RECLEN/2],acount;
  2002.     char neg, *s, sbuf[MAX_C+1], *reg, *regex(), *regcmp(), *index(), *strtok();
  2003.  
  2004.     user_str (sbuf,"Articles or title search string : ",1,Pattern);
  2005.     if (sbuf[0] == '!')
  2006.     {
  2007.         neg = '!';
  2008.         s = sbuf+1;
  2009.     }
  2010.     else
  2011.     {
  2012.         neg = '\0';
  2013.         s = sbuf;
  2014.     }
  2015.     for (i=0; s[i] != '\0'; ++i)
  2016.     {
  2017.         if (index(List_sep,s[i]) == NULL)
  2018.         {
  2019.             if (s[i] < '0' || s[i] > '9')
  2020.                 break;
  2021.         }
  2022.     }
  2023.     acount = 0;
  2024.  
  2025.     if (s[i] == '\0')
  2026.     {
  2027.         for (s = strtok(s,List_sep); s != NULL; s = strtok(NULL,List_sep))
  2028.         {
  2029.             anum[acount] = atoi(s);
  2030.             ++acount;
  2031.         }
  2032.     }
  2033.     else
  2034.     {
  2035.         /* we save old input only if NOT a list of article numbers */
  2036.         strcpy(Pattern,sbuf);
  2037.         if (s[0] == ART_MARK)
  2038.         {
  2039.             for (i=0; i < Page.h.artnum; ++i)
  2040.             {
  2041.                 if (Page.b[i].art_mark == ART_MARK)
  2042.                 {
  2043.                     anum[acount] = Page.b[i].art_id;
  2044.                     ++acount;
  2045.                 }
  2046.             }
  2047.         }
  2048.         else
  2049.         {
  2050.             reg = regcmp(s,(char *) 0);
  2051.             if (reg != NULL)
  2052.             {
  2053.                 for (i=0; i < Page.h.artnum; ++i)
  2054.                 {
  2055.                     if (regex(reg,Page.b[i].art_t) != NULL)
  2056.                     {
  2057.                         anum[acount] = Page.b[i].art_id;
  2058.                         ++acount;
  2059.                     }
  2060.                 }
  2061.                 regfree (reg);
  2062.             }
  2063.             else
  2064.                 preinfo ("bad regular expression syntax");
  2065.         }
  2066.     }
  2067.  
  2068.     /* algorithm is inefficient, but we're only handling a few numbers */
  2069.     *list = '\0';
  2070.     for (i=0; i < Page.h.artnum; ++i)
  2071.     {
  2072.         for (j=0; j < acount && anum[j] != Page.b[i].art_id; ++j)
  2073.             ;
  2074.         if (neg == '!')
  2075.         {
  2076.             if (j < acount)
  2077.                 continue;
  2078.         }
  2079.         else
  2080.         {
  2081.             if (j >= acount)
  2082.                 continue;
  2083.         }
  2084.         sprintf (list,"%d ",Page.b[i].art_id);
  2085.         list += strlen(list);
  2086.     }
  2087. }
  2088. SHAR_EOF
  2089. fi # end of overwriting check
  2090. echo shar: extracting "'vnglob.c'" '(1473 characters)'
  2091. if test -f 'vnglob.c'
  2092. then
  2093.     echo shar: will not over-write existing file "'vnglob.c'"
  2094. else
  2095. cat << \SHAR_EOF > 'vnglob.c'
  2096. /*
  2097. ** vn news reader.
  2098. **
  2099. ** vnglob.c - global variables - see string.c also
  2100. **
  2101. ** see copyright disclaimer / history in vn.c source file
  2102. */
  2103.  
  2104. #include <stdio.h>
  2105. #include "config.h"
  2106. #include "head.h"
  2107. #include "tune.h"
  2108. #include "node.h"
  2109. #include "page.h"
  2110.  
  2111. /*
  2112.     global data structure
  2113. */
  2114. NODE **Newsorder = NULL;    /* in order of fw_group calls */
  2115.  
  2116. char *Editor, *Ps1, *Printer;
  2117.  
  2118. int (*Massage)() = NULL;
  2119. int (*Headedit)() = NULL;
  2120. int (*Postfunc)() = NULL;
  2121. int (*Mailfunc)() = NULL;
  2122.  
  2123. char Erasekey, Killkey;        /* user keys from stty */
  2124. char *Orgdir;            /* .newsrc file, and original pwd */
  2125. char *Savefile = DEF_SAVE;    /* file in which to save articles */
  2126. char *Savedir;            /* default directory for saved articles */
  2127. char *Ccfile;            /* author_copy file, stored /bin/mail fmt */
  2128. char *Home;            /* user's home */
  2129.  
  2130. int Rot;    /* rotation */
  2131. int Headflag;    /* header printing flag */
  2132. int Digest;    /* if non-zero, digest article */
  2133. int More;    /* if non-zero, clear screen between each page.  Set by */
  2134.         /* user's MORE environment variable; if `-c', then set true */
  2135.  
  2136. char *Ku, *Kd, *Kl, *Kr;    /* Cursor movement capabilities */
  2137.  
  2138. /* character translation arrays for commands */
  2139. char Cxitop[128], Cxitor[128], Cxrtoi[128], Cxptoi[128];
  2140.  
  2141. /*
  2142.     cur_page - current page displayed;
  2143.     lrec - last record
  2144.     l_allow - lines allowed for article display
  2145.     c_allow - columns allowed
  2146.     ncount = newsorder index
  2147. */
  2148. int Cur_page, Lrec, L_allow, C_allow, Ncount;
  2149.  
  2150. int Nounsub, Listfirst;
  2151. /*
  2152.     current page
  2153. */
  2154. PAGE Page;
  2155. SHAR_EOF
  2156. fi # end of overwriting check
  2157. #    End of shell archive
  2158. exit 0
  2159.